package org.dreamwork.cai.monitor.managed;

import com.google.gson.GsonBuilder;
import org.dreamwork.cai.annotation.ARemoteServiceDiscoverer;
import org.dreamwork.cai.managed.RemoteServiceDiscoverer;
import org.dreamwork.cai.monitor.ws.Command;
import org.dreamwork.cai.monitor.ws.MonitorWebSocket;
import org.dreamwork.cai.srf.ServiceRouteFrame;
import org.dreamwork.cai.tools.Const;
import org.dreamwork.concurrent.broadcast.ILocalBroadcastReceiver;
import org.dreamwork.concurrent.broadcast.ILocalBroadcastService;
import org.dreamwork.injection.IObjectContext;
import org.dreamwork.websocket.WebSocketManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import javax.servlet.ServletContext;

@Resource
@ARemoteServiceDiscoverer (buildLocalStub = false)
public class RemoteServiceMonitor extends RemoteServiceDiscoverer {
    private final Logger logger = LoggerFactory.getLogger (RemoteServiceMonitor.class);

/*
    boolean[] -> [Z
    byte[] -> [B
    short[] -> [S
    char[] -> [C
    int[] -> [I
    long[] -> [J
    float[] -> [F
    double[] -> [D
*/

    @Resource
    private ILocalBroadcastService service;

    private ILocalBroadcastReceiver receiver;

    @Override
    public void perform (IObjectContext ctx) throws Exception {
        super.perform (ctx);

        if (service != null) {
            ServletContext app = ctx.getBean (ServletContext.class);
            System.out.println ("app - " + app);
            service.register (Const.Category.CAT_SRF_EVENT, receiver = message -> {
                if (message.what == Const.SRF.BUILT) {
                    ServiceRouteFrame srf = (ServiceRouteFrame) message.arg;
                    {
                        logger.info ("received a srf from {}", srf.host);
                        String content = new GsonBuilder ().setPrettyPrinting ().create ().toJson (srf);
                        logger.info ("\r\n{}", content);
                    }

                    notify ("update", srf);
                } else if (message.what == Const.SRF.DESTROY) {
                    notify ("withdrawn", message.arg);
                } else {
                    logger.info ("received a local broadcast, what = {}", message.what);
                }
            });
        }
    }

    private void notify (String action, Object arg) {
        WebSocketManager.fireDataChanged (MonitorWebSocket.class, new Command (action, arg));
    }

    @Override
    protected void beforeDestroy () {
        logger.info ("removing the local broadcast receiver ...");
        if (receiver != null) {
            service.unregister (Const.Category.CAT_SRF_EVENT, receiver);
        }
    }
}
